package com.dbms.transaction;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 事务管理器（TransactionManager）
 * 核心职责：
 * 1. 管理事务的完整生命周期（创建、提交、中止）
 * 2. 生成全局唯一的事务ID（支持并发环境下的原子性操作）
 * 3. 维护当前活跃事务的映射关系，便于快速查询和状态管理
 *
 * 设计特点：
 * - 使用原子整数（AtomicInteger）确保事务ID生成的线程安全性
 * - 通过哈希表（Map）存储活跃事务，实现O(1)复杂度的事务查询
 */
public class TransactionManager {

    /**
     * 下一个待分配的事务ID：原子整数确保并发环境下ID唯一且递增
     * 初始值为0，每次创建新事务时通过incrementAndGet()原子递增获取新ID
     */
    private final AtomicInteger nextTransactionId = new AtomicInteger(0);

    /**
     * 当前活跃事务的映射表：key=事务ID，value=事务实例（Transaction）
     * 仅存储处于RUNNING状态的事务，事务提交（COMMITTED）或中止（ABORTED）后会从表中移除
     */
    private final Map<Integer, Transaction> transactionMap = new HashMap<>();

    /**
     * 获取事务ID生成器（主要用于调试或扩展，不建议外部直接修改）
     * @return 原子整数对象（AtomicInteger），管理下一个待分配的事务ID
     */
    public AtomicInteger getNextTransactionId() {
        return nextTransactionId;
    }

    /**
     * 获取当前活跃事务的映射表（主要用于调试或状态检查）
     * @return 哈希表（Map<Integer, Transaction>），存储活跃事务的ID与实例映射
     */
    public Map<Integer, Transaction> getTransactionMap() {
        return transactionMap;
    }

    /**
     * 开始一个新事务：生成唯一ID、创建事务实例、加入活跃事务管理
     * @return 新创建的事务实例（Transaction），初始状态为RUNNING
     */
    public Transaction begin() {
        // 1. 原子递增生成唯一事务ID（避免并发环境下ID重复）
        int txnId = nextTransactionId.incrementAndGet();
        // 2. 创建事务实例，初始状态为RUNNING
        Transaction newTxn = new Transaction(txnId);
        // 3. 将新事务加入活跃事务映射表，便于后续管理（提交/回滚时查找）
        transactionMap.put(txnId, newTxn);
        return newTxn;
    }

    /**
     * 提交指定事务：更新事务状态为已提交，并从活跃事务表中移除
     * @param txn 待提交的事务实例（必须处于RUNNING状态）
     * 说明：在完整的数据库系统中，此方法会触发COMMIT日志写入和数据刷盘，
     * 此处仅完成事务状态管理和映射表清理，具体持久化逻辑由LogManager和BufferPoolManager实现
     */
    public void commit(Transaction txn) {
        // 1. 将事务状态更新为COMMITTED（标记事务已成功完成）
        txn.setState(Transaction.State.COMMITTED);
        // 2. （注：完整系统需在此处调用LogManager写入COMMIT日志并刷盘）
        // 3. 将事务从活跃事务表中移除（事务已结束，无需继续跟踪）
        transactionMap.remove(txn.getTransactionId());
    }

    /**
     * 中止（回滚）指定事务：更新事务状态为已中止，并从活跃事务表中移除
     * @param txn 待中止的事务实例（必须处于RUNNING状态）
     * 说明：实际的回滚逻辑（执行Undo操作，撤销事务对数据的修改）由DBMS核心层（如DbmsCore）实现，
     * 此处仅完成事务状态管理和映射表清理，具体数据回滚依赖LogManager的日志记录
     */
    public void rollback(Transaction txn) {
        // 1. 将事务状态更新为ABORTED（标记事务已撤销）
        txn.setState(Transaction.State.ABORTED);
        // 2. （注：完整系统需在此处触发回滚逻辑，通过LogManager读取事务日志执行Undo操作）
        // 3. 将事务从活跃事务表中移除（事务已结束，无需继续跟踪）
        transactionMap.remove(txn.getTransactionId());
    }

    /**
     * 根据事务ID查询当前活跃的事务实例
     * @param txnId 待查询的事务ID
     * @return 事务实例（Transaction），若事务不存在或已结束则返回null
     */
    public Transaction getTransaction(int txnId) {
        return transactionMap.get(txnId);
    }
}